#include "StorageDevice.h"

//http://elm-chan.org/docs/mmc/mmc_e.html

#define CMD0    0X00
#define CMD1    0X01
#define CMD8    0X08
#define CMD9    0X09
#define CMD10   0X0A
#define CMD13   0X0D
#define CMD17   0X11
#define CMD24   0X18
#define CMD25   0X19
#define CMD32   0X20
#define CMD33   0X21
#define CMD38   0X26
#define CMD55   0X37
#define CMD58   0X3A
#define ACMD23  0X17
#define ACMD41  0X29


#define R1_READY_STATE        0X00
#define R1_IDLE_STATE         0X01
#define R1_ILLEGAL_COMMAND    0X04
#define DATA_START_BLOCK      0XFE
#define STOP_TRAN_TOKEN       0XFD
#define WRITE_MULTIPLE_TOKEN  0XFC
#define DATA_RES_MASK         0X1F
#define DATA_RES_ACCEPTED     0X05



/** init timeout ms */
#define SD_INIT_TIMEOUT 3000000
/** erase timeout ms */
#define SD_ERASE_TIMEOUT 300000
/** read timeout ms */
#define SD_READ_TIMEOUT 300000
/** write time out ms */
#define SD_WRITE_TIMEOUT 600000

// SD card errors

#define SD_CARD_ERROR_CMD0                1 /** timeout error for command CMD0 */
#define SD_CARD_ERROR_CMD8                2 /** CMD8 was not accepted - not a valid SD card*/
#define SD_CARD_ERROR_CMD17               3 /** card returned an error response for CMD17 (read block) */
#define SD_CARD_ERROR_CMD24               4 /** card returned an error response for CMD24 (write block) */
#define SD_CARD_ERROR_CMD25               5/**  WRITE_MULTIPLE_BLOCKS command failed */
#define SD_CARD_ERROR_CMD58               6/** card returned an error response for CMD58 (read OCR) */
#define SD_CARD_ERROR_ACMD23              7/** SET_WR_BLK_ERASE_COUNT failed */
#define SD_CARD_ERROR_ACMD41              8/** card's ACMD41 initialization process timeout */
#define SD_CARD_ERROR_BAD_CSD             9/** card returned a bad CSR version field */
#define SD_CARD_ERROR_ERASE               10/** erase block group command failed */
#define SD_CARD_ERROR_ERASE_SINGLE_BLOCK  11/** card not capable of single block erase */
#define SD_CARD_ERROR_ERASE_TIMEOUT       12/** Erase sequence timed out */
#define SD_CARD_ERROR_READ                13/** card returned an error token instead of read data */
#define SD_CARD_ERROR_READ_REG            14/** read CID or CSD failed */
#define SD_CARD_ERROR_READ_TIMEOUT        15/** timeout while waiting for start of read data */
#define SD_CARD_ERROR_STOP_TRAN           16/** card did not accept STOP_TRAN_TOKEN */
#define SD_CARD_ERROR_WRITE               17/** card returned an error token as a response to a write operation */
#define SD_CARD_ERROR_WRITE_BLOCK_ZERO    18/** attempt to write protected block zero */
#define SD_CARD_ERROR_WRITE_MULTIPLE      19/** card did not go ready for a multiple block write */
#define SD_CARD_ERROR_WRITE_PROGRAMMING   20/** card returned an error to a CMD13 status check after a write */
#define SD_CARD_ERROR_WRITE_TIMEOUT       21/** timeout occurred during write programming */
#define SD_CARD_ERROR_SCK_RATE            22/** incorrect rate selected */


/** Standard capacity V1 SD card */
#define SD_CARD_TYPE_SD1 1
/** Standard capacity V2 SD card */
#define SD_CARD_TYPE_SD2 2
/** High Capacity SD card */
#define SD_CARD_TYPE_SDHC 3

#define SD_CARD_TYPE_MMC 4

//------------------------------------------------------------------------------
/**
 * \class Sd2Card
 * \brief Raw access to SD and SDHC flash memory cards.
 */
class Sd2Card : public StorageDevice {
 public:
  int chipSelectPin_;
  int error;
  int status_;
  int type_;

  void readEnd(void);

  int cardAcmd(int cmd, unsigned int arg);

  void chipSelectHigh();
  void chipSelectLow();

  int waitNotBusy(int timeoutMillis);

  int writeData(int token, const char* src);
  
  void printType();
  
  int cardCommand(int cmd, unsigned int arg);
  int cardCommand2(int cmd);
  
  int initError;
  int init(int chipSelectPin);
  int getSize(int chipSelectPin);
  
  int waitStartBlock(void);

};
